/*
 * xAPmessage.java
 *
 * Java class used to store incoming xAP messages
 *
 * Copyright (c) 2009 Daniel Berenguer <dberenguer@usapiens.com>
 *
 * This file is part of the jxAP project.
 *
 * OPNODE is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * OPNODE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with canTracer; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * 11/08/09 by Daniel Berenguer : first version
 */

package xAP;

/********************************************************************************************
 * xAPmessage class
 *
 * Class used to store xAP message data. Create a new xAPmessage object whenever a new xAP
 * message is received.
 *
 *********************************************************************************************/
public class xAPmessage
{
    /********************************************************************************************
    * Public member variables
    ********************************************************************************************/
    // Whole message
    public String message;
    // xAP header fields
    public short version = 0;       // xAP version
    public short hop = 0;           // Hop count
    public String uid = "";         // xAP UID
    public String xClass = "";      // xAP class
    public String source = "";      // xAP source
    public String target = "";      // xAP target
    public short interval = 0;      // Hearbeat interval

    public String body = "";        // Message body

    /********************************************************************************************
    * xAPmessage
    *
    * Class constructor
    *
    * 'message'     xAP message string
    *
    ********************************************************************************************/
    public xAPmessage(String strMessage)
    {
        message = strMessage;
        
        try
        {
            xAPreadHeader(message);
        }
        catch(xAPexception e)
        {
            e.display();
        }
    }
    public xAPmessage()
    {
        
    }

   /********************************************************************************************
    * xAPreadHeader
    *
    * Read xAP header and fill class members
    *
    * 'message'     xAP message string
    *
    ********************************************************************************************/
    private void xAPreadHeader(String message) throws xAPexception
    {
        String strHeaderCont;
        int intStart = 0, intEnd;

        // Reach the end of the header
        if ((intEnd = message.indexOf("}\n")) == -1)
            throw new xAPexception("Message header malformed");

        if (message.charAt(0) == '\n')
            intStart++;

        // Verify message header
        if (message.substring(intStart, 13).compareToIgnoreCase("xap-header\n{\n") == 0)
            intStart = 13;
        else if (message.substring(intStart, 12).compareToIgnoreCase("xap-hbeat\n{\n") == 0)
            intStart = 12;
        else
            throw new xAPexception("Message header malformed");

        // Store header contents
        strHeaderCont = message.substring(intStart, intEnd);
        intEnd += 2;

        // Extract xAP data from header

        // Get version number
        version = xAPgetVersion(strHeaderCont);
        // Get hop number
        hop = xAPgetHop(strHeaderCont);
        // Get UID
        uid = xAPgetUID(strHeaderCont);
        // Get Class
        xClass = xAPgetClass(strHeaderCont);
        // Get Source
        source = xAPgetSource(strHeaderCont);
        // Get Target
        if (xAPcontainsTarget(xClass) == true)
            target = xAPgetTarget(strHeaderCont);
        // Get Interval
        if (intStart == 12)
            interval = xAPgetInterval(strHeaderCont);
        // Store message body
        body = message.substring(intEnd);
    }

   /********************************************************************************************
    * xAPgetVersion
    *
    * Get xAP version from xAP header
    *
    * 'headCont'        header contents
    *
    *  Return:
    *   Version
    ********************************************************************************************/
    private short xAPgetVersion(String headCont)
    {
        int intStart = 0, intEnd;
        String strKey;

        while ((intEnd = headCont.indexOf('=', intStart)) != -1)
        {
            // Get keyword
            strKey = headCont.substring(intStart, intEnd);

            intStart = intEnd + 1;
            intEnd = headCont.indexOf('\n', intStart);
            if (strKey.compareToIgnoreCase("v") == 0)
                return Short.parseShort(headCont.substring(intStart, intEnd));
            intStart = intEnd + 1;
        }

        return 0;
    }

   /********************************************************************************************
    * xAPgetHop
    *
    * Get Hop number from xAP header
    *
    * 'headCont'        Header contents
    *
    *  Return:
    *   hop number
    ********************************************************************************************/
    private short xAPgetHop(String headCont)
    {
        int intStart = 0, intEnd;
        String strKey;

        while ((intEnd = headCont.indexOf('=', intStart)) != -1)
        {
            // Get keyword
            strKey = headCont.substring(intStart, intEnd);

            intStart = intEnd + 1;
            intEnd = headCont.indexOf('\n', intStart);
            if (strKey.compareToIgnoreCase("hop") == 0)
                return Short.parseShort(headCont.substring(intStart, intEnd));
            intStart = intEnd + 1;
        }

        return 0;
    }

   /********************************************************************************************
    * xAPgetUID
    *
    * Get UID from xAP header
    *
    * 'headCont'        Header contents
    *
    *  Return:
    *   UID string
    ********************************************************************************************/
    private String xAPgetUID(String headCont)
    {
        int intStart = 0, intEnd;
        String strKey;

        while ((intEnd = headCont.indexOf('=', intStart)) != -1)
        {
            // Get keyword
            strKey = headCont.substring(intStart, intEnd);

            intStart = intEnd + 1;
            intEnd = headCont.indexOf('\n', intStart);
            if (strKey.compareToIgnoreCase("uid") == 0)
                return headCont.substring(intStart, intEnd);
            intStart = intEnd + 1;
        }

        return null;
    }

   /********************************************************************************************
    * xAPgetClass
    *
    * Get class from xAP header
    *
    * 'headCont'        Header contents
    *
    *  Return:
    *   Class string
    ********************************************************************************************/
    private String xAPgetClass(String headCont)
    {
        int intStart = 0, intEnd;
        String strKey;

        while ((intEnd = headCont.indexOf('=', intStart)) != -1)
        {
            // Get keyword
            strKey = headCont.substring(intStart, intEnd);

            intStart = intEnd + 1;
            intEnd = headCont.indexOf('\n', intStart);
            if (strKey.compareToIgnoreCase("class") == 0)
                return headCont.substring(intStart, intEnd);
            intStart = intEnd + 1;
        }

        return null;
    }

   /********************************************************************************************
    * xAPgetSource
    *
    * Get source field from xAP header
    *
    * 'headCont'        Header contents
    *
    *  Return:
    *   Source string
    ********************************************************************************************/
    private String xAPgetSource(String headCont)
    {
        int intStart = 0, intEnd;
        String strKey;

        while ((intEnd = headCont.indexOf('=', intStart)) != -1)
        {
            // Get keyword
            strKey = headCont.substring(intStart, intEnd);

            intStart = intEnd + 1;
            intEnd = headCont.indexOf('\n', intStart);
            if (strKey.compareToIgnoreCase("source") == 0)
                return headCont.substring(intStart, intEnd);
            intStart = intEnd + 1;
        }

        return null;
    }

   /********************************************************************************************
    * xAPgetTarget
    *
    * Get target field from xAP header
    *
    * 'headCont'        Header contents
    *
    *  Return:
    *   Target string
    ********************************************************************************************/
    private String xAPgetTarget(String headCont)
    {
        int intStart = 0, intEnd;
        String strKey;

        while ((intEnd = headCont.indexOf('=', intStart)) != -1)
        {
            // Get keyword
            strKey = headCont.substring(intStart, intEnd);

            intStart = intEnd + 1;
            intEnd = headCont.indexOf('\n', intStart);
            if (strKey.compareToIgnoreCase("target") == 0)
                return headCont.substring(intStart, intEnd);
            intStart = intEnd + 1;
        }

        return null;
    }

   /********************************************************************************************
    * xAPgetInterval
    *
    * Get Interval from xAP header
    *
    * 'headCont'        Header contents
    *
    *  Return:
    *   interval
        ********************************************************************************************/
    private short xAPgetInterval(String headCont)
    {
        int intStart = 0, intEnd;
        String strKey;

        while ((intEnd = headCont.indexOf('=', intStart)) != -1)
        {
            // Get keyword
            strKey = headCont.substring(intStart, intEnd);

            intStart = intEnd + 1;
            intEnd = headCont.indexOf('\n', intStart);
            if (strKey.compareToIgnoreCase("interval") == 0)
                return Short.parseShort(headCont.substring(intStart, intEnd));
            intStart = intEnd + 1;
        }

        return 0;
    }

   /********************************************************************************************
    * xAPcontainsTarget
    *
    * Check if the xAP class passed as argument should have an associated "target" field in the
    * message header
    *
    * 'xClass'          xAP class
    *
    *  Return:
    *   true if the message has to contain a "target" field in the message header
    *   false otherwise
    ********************************************************************************************/
    private boolean xAPcontainsTarget(String xClass)
    {
        String strAllowedClass[] = {"xAPBSC.cmd", "xAPBSC.query", };
        int i;

        for(i=0 ; i<strAllowedClass.length; i++)
        {
            if (xClass.compareToIgnoreCase(strAllowedClass[i]) == 0)
                return true;
        }

        return false;
    }

   /********************************************************************************************
    * send
    *
    * Send xAP message
    *
    ********************************************************************************************/
    public void send()
    {
        // Send xAP BSC command
        try
        {
            drvCore.send_xAPmessage(message);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}
